<template>
  <div>
    <el-breadcrumb separator="/" class="nav_ul">
      <el-breadcrumb-item :to="{ path: './welcome' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>权限管理</el-breadcrumb-item>
      <el-breadcrumb-item>角色列表</el-breadcrumb-item>
    </el-breadcrumb>
    <el-card class="box-card">
      <el-row>
        <el-col align="left">
          <el-button type="primary" @click="addRolesOn = true">添加按钮</el-button>
        </el-col>
      </el-row>
      <el-table :data="roleList" style="width: 100%" stripe border>
        <el-table-column type="expand"> <!-- expand定义展开行 -->
          <!-- 使用作用域插槽传递数据-->
          <template slot-scope="scope">
            <el-row class="row01 he_center" v-for="item in scope.row.children" :key="item.id">
              <el-col :span="5">
                  <el-tag closable @close="removeRightById(scope.row,item.id)">{{item.authName}}</el-tag> <i class="el-icon-caret-right"></i>
              </el-col>
              <el-col :span="19">
                <el-row class="row01 he_center" v-for="item2 in item.children" :key="item2.id">
                  <el-col :span="8">
                    <el-tag type="success" closable @close="removeRightById(scope.row,item2.id)">{{item2.authName}}</el-tag> <i class="el-icon-caret-right"></i>
                  </el-col>
                  <el-col :span="16">
                    <el-tag type="warning" closable @close="removeRightById(scope.row,item3.id)" class="wa01" v-for="item3 in item2.children" :key="item3.id">{{item3.authName}}</el-tag>
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
          </template>
        </el-table-column>
        <el-table-column label="#" width="80" type="index" ></el-table-column>
        <el-table-column label="角色名称" prop="roleName" ></el-table-column>
        <el-table-column label="角色描述" prop="roleDesc" ></el-table-column>
        <el-table-column label="操作" align="center" min-width="300px">
          <template slot-scope="scope">
            <el-button type="primary" icon="el-icon-edit" size="mini" @click="editRole(scope.row.id)">编辑</el-button>
            <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteRole(scope.row.id)">删除</el-button>
            <el-tooltip class="item" effect="dark" content="角色授权" placement="top" :enterable="false">
              <el-button type="warning" icon="el-icon-setting" size="mini" @click="rolesRights(scope.row)">分配权限</el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <!-- 添加角色 -->
      <el-dialog
        title="添加角色"
        :visible.sync="addRolesOn"
        width="50%" :before-close="closeAddRolse">
        <el-form :model="addRoleForm" :rules="addRoleRules" ref="addRoleRef" label-width="100px" class="add-ruleForm">
          <el-form-item label="角色名称" prop="roleName">
            <el-input v-model="addRoleForm.roleName"></el-input>
          </el-form-item>
          <el-form-item label="角色描述" prop="roleDesc">
            <el-input v-model="addRoleForm.roleDesc"></el-input>
          </el-form-item>
        </el-form>

        <span slot="footer" class="dialog-footer">
          <el-button @click="closeAddRolse">取 消</el-button>
          <el-button type="primary" @click="addRoles">确 定</el-button>
        </span>
      </el-dialog>
      <!-- 修改角色 -->
      <el-dialog
        title="修改角色"
        :visible.sync="editRolesOn"
        width="50%" :before-close="closeEditRolse">
        <el-form :model="editRoleForm" :rules="editRoleRules" ref="editRoleRef" label-width="100px" class="edit-ruleForm">
          <el-form-item label="角色Id" prop="roleId">
            <el-input v-model="editRoleForm.roleId" disabled></el-input>
          </el-form-item>
          <el-form-item label="角色名称" prop="roleName">
            <el-input v-model="editRoleForm.roleName"></el-input>
          </el-form-item>
          <el-form-item label="角色描述" prop="roleDesc">
            <el-input v-model="editRoleForm.roleDesc"></el-input>
          </el-form-item>
        </el-form>

        <span slot="footer" class="dialog-footer">
          <el-button @click="closeEditRolse">取 消</el-button>
          <el-button type="primary" @click="editRoleData">确 定</el-button>
        </span>
      </el-dialog>
      <!-- 角色授权 -->
      <el-dialog
        title="角色授权"
        :visible.sync="rolesRightsOn"
        width="50%" :before-close="closeRolesRights">
            <!--按顺序相关配置： 树状图数据、是否可选、唯一标识、选中数据、配置选项 -->
            <el-tree
              :data="rightTree"
              show-checkbox
              node-key="id"
              :default-checked-keys="rightsSelected"
              :default-expand-all="true"
              :props="defaultProps" ref="roleRightsRef">
            </el-tree>
        <span slot="footer" class="dialog-footer">
          <el-button @click="closeRolesRights">取 消</el-button>
          <el-button type="primary" @click="rolesRightsData">确 定</el-button>
        </span>
      </el-dialog>
    </el-card>
  </div>
</template>

<script>
export default {
  data () {
    return {
      addRolesOn: false, // 添加角色表单开关
      addRoleForm: { // 添加角色请求参数
        roleName: '',
        roleDesc: ''
      },
      addRoleRules: { // 添加角色预验证
        roleName: [
          { required: true, message: '请输入角色名称', trigger: 'blur' },
          { min: 3, max: 15, message: '长度在 3 到 15 个字符', trigger: 'blur' }
        ]
      },
      editRolesOn: false, // 编辑角色表单开关
      editRoleForm: { // 编辑角色请求参数
        id: 0,
        roleName: '',
        roleDesc: ''
      },
      editRoleRules: { // 编辑角色预验证
        roleId: [
          { required: true }
        ],
        roleName: [
          { required: true, message: '请输入角色名称', trigger: 'blur' },
          { min: 1, max: 15, message: '长度在 1 到 15 个字符', trigger: 'blur' }
        ]
      },
      rightTree: [], // 所有权限树状数据
      roleList: [], // 角色权限列表
      rolesRightsOn: false, // 角色权限表单开关
      rightsSelected: [], // 选中权限ID列表
      thisRoleId: '',
      defaultProps: { // 树状图配置
        children: 'children', // 指定子树为节点对象的某个属性值
        label: 'authName' // 指定节点标签为节点对象的某个属性值
      }
    }
  },
  created () {
    // 获取所有角色数据
    this.getRoleList()
  },
  methods: {
    // 获取所有角色数据
    async getRoleList () {
      const { data: res } = await this.$http.get('roles')
      if (res.meta.status !== 200) {
        return this.$message.error('获取权限列表失败')
      }
      this.roleList = res.data
    },
    // 关闭添加角色表单行为
    closeAddRolse () {
      this.addRolesOn = false // 关闭添加角色开关
      this.addRoleForm = {} // 初始化添加角色数据
    },
    // 添加角色行为
    addRoles () {
      this.$refs.addRoleRef.validate(async (valid) => {
        if (valid) { // 判断是否通过预验证
          const { data: res } = await this.$http.post('roles', this.addRoleForm)
          if (res.meta.status !== 201) {
            return this.$message.error(res.meta.msg) // 失败提示信息，并return终止操作
          }
          this.$message.success(res.meta.msg) // 成功提示信息
          this.getRoleList() // 刷新角色数据
          this.closeAddRolse() // 关闭添加角色
        }
      })
    },
    // 关闭编辑角色行为
    closeEditRolse () {
      this.editRolesOn = false // 关闭编辑角色开关
      this.editRoleForm = {} // 初始化编辑角色数据
    },
    // 根据 ID 查询角色
    async editRole (id) {
      const { data: res } = await this.$http.get('roles/' + id)
      if (res.meta.status !== 200) {
        return this.$message(res.meta.msg) // 失败提示信息，并return终止操作
      }
      this.editRoleForm = res.data // 显示角色信息
      this.editRolesOn = true // 打开编辑角色
    },
    // 编辑提交角色
    editRoleData () {
      this.$refs.editRoleRef.validate(async (valid) => {
        if (valid) { // 判断是否通过预验证
          const { data: res } = await this.$http.put('roles/' + this.editRoleForm.roleId, this.editRoleForm)
          if (res.meta.status !== 200) {
            return this.$message.error(res.meta.msg) // 失败提示信息，并return终止操作
          }
          this.getRoleList() // 刷新角色数据
          this.$message.success(res.meta.msg) // 成功提示信息
          this.closeEditRolse()
        }
      })
    },
    // 根据ID删除指定角色
    async deleteRole (id) {
      const confirRole = await this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(err => err)
      if (confirRole !== 'confirm') { // 判断用户是否操作取消按钮
        return this.$message.error('取消删除该角色') // return 终止后面操作
      }
      const { data: res } = await this.$http.delete('roles/' + id)
      if (res.meta.status !== 200) {
        return this.$message.error(res.meta.msg)
      }
      this.$message.success(res.meta.msg)
      this.getRoleList() // 刷新角色数据
    },
    // 关闭角色授权
    closeRolesRights () {
      this.rolesRightsOn = false
      this.rightsSelected = [] // 清空角色授权树状图选中
    },
    // 递归选中ID给到选中数组
    recursionSelectId (node, array) {
      if (!node.children) { // 判断是三级数据则存储ID并return中止递归
        return array.push(node.id)
      }
      node.children.forEach((item) => { // 遍历数据children
        this.recursionSelectId(item, array) // 递归数据遍历
      })
    },
    // 打开角色授权树状图
    async rolesRights (role) {
      const { data: res } = await this.$http.get('rights/tree')
      if (res.meta.status !== 200) {
        return this.$message.error(res.meta.msg)
      }
      this.rightTree = res.data // 存储所有权限树状数据
      this.recursionSelectId(role, this.rightsSelected) // 调用递归，传入角色权限和权限选中数组
      this.thisRoleId = role.id
      this.rolesRightsOn = true // 显示角色授权树状图
    },
    // 角色授权
    async rolesRightsData () {
      const rids = this.$refs.roleRightsRef.getCheckedKeys().join(',')
      const { data: res } = await this.$http.post('roles/' + this.thisRoleId + '/rights', { rids: rids })
      if (res.meta.status !== 200) {
        return this.$message.error(res.meta.msg)
      }
      this.$message.success(res.meta.msg)
      this.getRoleList() // 刷新角色数据
      this.closeRolesRights() // 关闭角色授权
    },
    // 根据ID删除指定权限行为
    async removeRightById (role, rightId) { // 传入角色数据(用于完成以下不关闭展开行刷新数据)和权限ID
      const confirmRight = await this.$confirm('此操作将永久删除该权限, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(err => err)
      if (confirmRight !== 'confirm') { // 判断用户是否操作取消按钮
        return this.$message.error('取消删除该权限')
      }
      // 用户操作了确定删除权限
      const { data: res } = await this.$http.delete('roles/' + role.id + '/rights/' + rightId)
      role.children = res.data // 不关闭展开行，直接刷新数据
    }
  }
}
</script>
<style scoped>
  .nav_ul {margin-bottom:20px;}
  .el-table {margin-top:20px;}
  .row01 {border-bottom:1px solid #eee;width:92%;margin:auto;}
  .row01:last-child {border-bottom:0;}
  .he_center {display:flex;align-items: center;}
  .wa01 {margin:10px 0;margin-right:20px;}
</style>
